Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: OpenDoc Programmer's Guide / Part 2 - Programming
Chapter 11 - OpenDoc Runtime Features


The Runtime Environment

The runtime model for the execution of part editors in the OpenDoc environ-
ment is different from that of conventional applications. This section discusses those differences in terms of the runtime process model, System Object Model runtime issues, and the part wrapper object. It also discusses name spaces, a runtime service provided by OpenDoc.

The OpenDoc Runtime Process

The OpenDoc document-centered approach requires a runtime process model significantly different from the classic application-centered process model. On personal-computer platforms, each process is usually owned by an application. This process provides the address space in which the application code executes as well as the memory for every document opened by that application. The operating system assigns a document to a process based on the document's type, an indication of which application created it.

In OpenDoc, a document no longer has a single type but is instead composed of many parts that may be of different types. Thus, the document, not any application, is the owner of the process. The document manages standard tasks such as handling the event loop, managing files, printing, and interacting with system menus, dialog boxes, and so on. In OpenDoc, some of this behavior is provided by a shared library called the document shell. The fact that individual parts in a document share this code is one reason why part editors can be significantly smaller than conventional applications.

The document shell has the following basic responsibilities:

The executable code of part editors is stored and accessed as shared libraries, independent of any process. (Note that part-editor code must be reentrant on the Mac OS because several instances of a part in a single document may use the same editor.) What the process provides is an address space for the contents of a particular document, along with any additional memory needed by the individual part editors. All state information used by any part editor is, with some minor exceptions, maintained in the processes of those documents that contain parts manipulated by the editor.

Multiprocess runtime model
The single-process-per-document model is not the only runtime model possible with OpenDoc. On platforms that provide fast process switching and efficient interprocess dispatch, the document shell process can run each part in a separate process.

CFM and the System Object Model

Two cornerstones of the OpenDoc runtime environment are dynamic linking, which allows compound documents to be assembled at runtime, and a language-neutral object model, which facilitates runtime compatibility of parts and minimizes the recompilation required by changes to OpenDoc or to part editors.

Dynamic linking on the Mac OS platform is provided by the Code Fragment Manager (CFM). The object model used by OpenDoc is the System Object Model (SOM). This section introduces some runtime aspects of CFM and SOM that are of interest to part-editor developers. (The particulars of writing SOM-based code are discussed in the section "Developing With SOMobjects and IDL".) For more information, see the SOM appendix of the OpenDoc Cookbook for the Mac OS.

Dynamic Linking

OpenDoc depends on dynamic linking to allow the appropriate executable code to be added to the runtime environment of a document. Before a document is opened, there is no way of knowing what part editors may be needed to manipulate its contents. The dynamic linking used by OpenDoc on the Mac OS relies on the Code Fragment Manager (CFM) to manipulate code fragments. The dynamic linking provided by CFM has the following capabilities:

SOM and Distributed Dispatching

System Object Model (SOM) objects are CORBA-compliant, meaning that
they follow the language-neutral distributed standards of the Common
Object Request Broker Architecture (CORBA),
established by the Object Management Group (OMG), an industry consortium. Compliance with
these standards mean that objects compiled in different languages or with different compilers can communicate with each other.

More than that, SOM objects running on different machines can communicate with each other. This distributed dispatching may be a future capability of OpenDoc and is therefore supported in these basic architectural features:

SOM Exception Handling

OpenDoc objects are SOM objects, and as such they follow the CORBA rules for handling exceptions. Every method call made to an OpenDoc object (including your part, as a subclass of ODPart) must therefore include an environment parameter (ev), a pointer to a value that can describe an error. For example, the CreateLinkSource method of ODDraft has the following prototype (in IDL):

ODLinkSource CreateLinkSource(in ODPart part);
The method takes a single parameter, of type ODPart. To use this method, however, a caller in C++ must supply two parameters:

MyLinkSource = MyDraft->CreateLinkSource(ev, somSelf);
If execution of the method results in an error condition, the receiver of the call (the draft object in this case) must place an exception code in the value pointed to by ev and return. The caller must therefore examine the ev parameter after every call to a SOM object to see if an exception has been raised.

All OpenDoc methods that you call, as well as all public methods of your part editor that you write, must return errors this way. These are the implications for your exception handling:

The environment variable is passed along through a sequence of calls and can be used in calls to both SOM and C++ objects. Here is how you can use it correctly:

For more information on the environment parameter and exceptions, see SOMObjects Developer Toolkit Users Guide and SOMObjects Developer Toolkit Programmers Reference Manual from IBM.

Any exception-handling scheme that you use must support this method of passing exceptions. An OpenDoc utility library (Except), described in the OpenDoc Cookbook for the Mac OS, helps you check the environment variable after each method call.

The Part-Wrapper Object

Your part first initializes itself when OpenDoc calls its InitPart or InitPartFromStorage method, as described in "Initializing and Reading a Part From Storage"partWrapper parameter of InitPart or InitPartFromStorage. That reference is to a part-wrapper object, a private object that OpenDoc creates and uses to represent your part.

The part wrapper keeps other parts of OpenDoc from having direct pointers to your part object; its only function is to delegate methods of ODPart to your part. Using a part wrapper gives OpenDoc more flexibility in manipulating parts. For example, use of a part wrapper allows OpenDoc to switch editors for a part without having to close and reopen the part's document.

You must use your part-wrapper reference in all calls to the OpenDoc interface that require you to pass a reference to yourself--for example, when registering your part for idle time. (Typically, if your part object keeps a field such as fSelf to hold a reference to itself, that field should contain the part-wrapper reference.) Specifically, you should never pass somSelf as a parameter to any OpenDoc method except when accessing objects such as extensions and embedded-frame iterators for which your part itself is the factory.

Part-wrapper methods
The interface to ODPart includes three part-wrapper methods--IsRealPart, GetRealPart, and ReleaseRealPart--that are intended for the part-wrapper object only. OpenDoc calls these methods when associating your part with or disassociating it from its part wrapper. When you subclass ODPart to create your part editor, do not override these methods.

Name Spaces

Each OpenDoc session provides a runtime service allowing you to define name spaces. A name space is an object that maps data types to values. It consists of a set of string-value pairs that associate the string (an ISO string) with the value (a 4-byte unsigned value, which could be a pointer to code).

For example, OpenDoc uses name spaces to represent the preferences of the user for binding parts (whose part kinds are represented by ISO strings) to part editors (represented by pointers to editor IDs).

Name spaces are a general-purpose runtime registry mechanism. You can use them to define global spaces in which to share information with other parts. You can define as many name spaces as you wish; the OpenDoc name-space manager keeps a list (which is itself a name space) of all currently defined name spaces.

For example, you can use a name space to create palettes or other controls to be shared among several parts. Use an ISO string to identify the name space itself and ISO strings to identify each of the controls it encompasses. You then can get pointers to the controls (if the name space has already been instantiated) or instantiate the name space and provide pointers to the controls (if your part is the first in the session to use the name space).

If you publish the ISO strings that define your name space and its contents, the name space can be used publicly. If you do not publish the names, you can still use the name space for your own private global variables.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
16 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help